﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DIPLib;
using System.IO;
using DIPLib.UI;
namespace DigitalImageProcessing
{
    public partial class MainForm : Form
    {
        Bitmap mProcessedBitmap;
        Bitmap mOriginalBitmap;
        Stack<Bitmap> mBitmapStack = new Stack<Bitmap>();
        Stack<Bitmap> mRedoBitmapStack = new Stack<Bitmap>();

        public MainForm()
        {
            InitializeComponent();
        }

        #region Open Image file, save file function
        private void openFile()
        {
            dlgOpenFile.Filter = "Bitmap Files|*.bmp; *.png";
            DialogResult result = dlgOpenFile.ShowDialog();
            if (result == DialogResult.OK)
            {
                Image img = Image.FromFile(dlgOpenFile.FileName);
                mOriginalBitmap = new Bitmap(img);
                pbImageViewer.Image = mOriginalBitmap;
                tool_save.Enabled = true;
            }

        }

        private void saveFile()
        {
            if (pbImageViewer.Image != null)
            {
                dlgSaveFile = new SaveFileDialog();
                dlgSaveFile.Filter = "BMP Files|*.bmp;|PNG Files|*.png;";
                Bitmap bmp = new Bitmap(pbImageViewer.Image);
                if (dlgSaveFile.ShowDialog() == DialogResult.OK && !dlgSaveFile.FileName.Equals(""))
                {
                    FileStream fs = (FileStream)dlgSaveFile.OpenFile();
                    switch (dlgSaveFile.FilterIndex)
                    {
                        case 1:
                            bmp.Save(fs, System.Drawing.Imaging.ImageFormat.Bmp);
                            break;
                        case 2:
                            bmp.Save(fs, System.Drawing.Imaging.ImageFormat.Png);
                            break;
                        default:
                            break;
                    }
                }
            }
        }
        #endregion

        #region Tool strip action perform
        private void tool_open_Click(object sender, EventArgs e)
        {
            openFile();
        }

        private void tool_save_Click(object sender, EventArgs e)
        {
            saveFile();
        }

        private void tool_viewHistogram_Click(object sender, EventArgs e)
        {
            if (pbImageViewer.Image != null)
            {
                DipOperations operations = new DipOperations(new Bitmap(pbImageViewer.Image));
                control_histogram.Visible = true;
                control_histogram.drawHistogramChart(operations.getHistogram(), Color.Red);
            }
        }

        private void tool_switchImage_Click(object sender, EventArgs e)
        {
            if (mProcessedBitmap != null && mBitmapStack.Count > 0)
            {
                if (pbImageViewer.Image == mProcessedBitmap)
                {
                    pbImageViewer.Image = mBitmapStack.Peek();
                }
                else
                {
                    pbImageViewer.Image = mProcessedBitmap;
                }
            }

        }

        private void tool_histogram_Click(object sender, EventArgs e)
        {
            if (pbImageViewer.Image != null)
            {
                mOriginalBitmap = new Bitmap(pbImageViewer.Image);
                DipOperations operations = new DipOperations(mOriginalBitmap);
                mBitmapStack.Push(mOriginalBitmap);
                mProcessedBitmap = operations.histogram();
                pbImageViewer.Image = mProcessedBitmap;
            }
        }

        private void tool_negative_Click(object sender, EventArgs e)
        {
            if (pbImageViewer.Image != null)
            {
                mOriginalBitmap = new Bitmap(pbImageViewer.Image);
                DipOperations operations = new DipOperations(mOriginalBitmap);
                mBitmapStack.Push(mOriginalBitmap);
                mProcessedBitmap = operations.negative();
                pbImageViewer.Image = mProcessedBitmap;
            }
        }

        private void tool_powerlaw_Click(object sender, EventArgs e)
        {
            if (pbImageViewer.Image != null)
            {
                mOriginalBitmap = new Bitmap(pbImageViewer.Image);
                mBitmapStack.Push(mOriginalBitmap);
                control_histogram.Visible = false;
                control_threshold.Visible = false;
                control_powerlaw.Gamma = 1;
                control_powerlaw.Visible = true;
                control_buttonOk.Visible = true;
                control_buttonCancel.Visible = true;
            }
        }

        private void tool_thresholding_Click(object sender, EventArgs e)
        {
            if (pbImageViewer.Image != null)
            {
                mOriginalBitmap = new Bitmap(pbImageViewer.Image);
                mBitmapStack.Push(mOriginalBitmap);
                control_powerlaw.Visible = false;
                control_histogram.Visible = false;
                control_threshold.Level = 128;
                control_threshold.Visible = true;
                control_buttonOk.Visible = true;
                control_buttonCancel.Visible = true;
            }
        }

        private void tool_logarithmic_Click(object sender, EventArgs e)
        {
            if (pbImageViewer.Image != null)
            {
                mOriginalBitmap = new Bitmap(pbImageViewer.Image);
                mBitmapStack.Push(mOriginalBitmap);
                DipOperations operations = new DipOperations(mOriginalBitmap);
                mProcessedBitmap = operations.logarithmic();
                pbImageViewer.Image = mProcessedBitmap;
            }
        }

        #endregion

        #region Event handle for component in control panel and main panel
        private void control_buttonOk_Click(object sender, EventArgs e)
        {
            mProcessedBitmap = new Bitmap(pbImageViewer.Image);
            control_histogram.Visible = false;
            control_threshold.Visible = false;
            control_powerlaw.Visible = false;
            control_buttonOk.Visible = false;
            control_buttonCancel.Visible = false;
        }

        private void control_threshold_ValuesChanged(object sender, EventArgs e)
        {
            DipOperations operations = new DipOperations(mOriginalBitmap);
            pbImageViewer.Image = operations.threshoding(control_threshold.Level);
        }

        private void control_powerlaw_ValuesChanged(object sender, EventArgs e)
        {
            DipOperations operations = new DipOperations(mOriginalBitmap);
            pbImageViewer.Image = operations.powerLaw(control_powerlaw.Gamma);
        }

        private void control_buttonCancel_Click(object sender, EventArgs e)
        {
            if (mBitmapStack.Count > 0)
            {
                pbImageViewer.Image = mBitmapStack.Pop();
                control_histogram.Visible = false;
                control_threshold.Visible = false;
                control_powerlaw.Visible = false;
                control_buttonOk.Visible = false;
                control_buttonCancel.Visible = false;
            }
        }

        private void dlgSaveFile_FileOk(object sender, CancelEventArgs e)
        {
            String fileName = dlgSaveFile.FileName;
        }

        private void pbImageViewer_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            openFile();
        }

        #endregion

        #region Event handle for menu item on menu bar
        private void menu_open_Click(object sender, EventArgs e)
        {
            openFile();
        }

        private void menu_save_Click(object sender, EventArgs e)
        {
            saveFile();
        }

        private void menu_exit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void menu_undo_Click(object sender, EventArgs e)
        {
            if (mBitmapStack.Count > 0)
            {
                mRedoBitmapStack.Push(new Bitmap(pbImageViewer.Image));
                pbImageViewer.Image = mBitmapStack.Pop();
            }
        }

        private void menu_redo_Click(object sender, EventArgs e)
        {
            if (mRedoBitmapStack.Count > 0)
            {
                mBitmapStack.Push(new Bitmap(pbImageViewer.Image));
                pbImageViewer.Image = mRedoBitmapStack.Pop();
            }
        }

        private void menu_viewHistogram_Click(object sender, EventArgs e)
        {
            if (pbImageViewer.Image != null)
            {
                DipOperations operations = new DipOperations(new Bitmap(pbImageViewer.Image));
                control_histogram.Visible = true;
                control_powerlaw.Visible = false;
                control_threshold.Visible = false;
                control_histogram.drawHistogramChart(operations.getHistogram(), Color.Red);
            }
        }


        private void menu_minfilter_Click(object sender, EventArgs e)
        {
            if (pbImageViewer.Image != null)
            {
                FilterSettingDialog dialog = new FilterSettingDialog();
                if (DialogResult.OK == dialog.ShowDialog())
                {
                    mOriginalBitmap = new Bitmap(pbImageViewer.Image);
                    DipOperations operations = new DipOperations(mOriginalBitmap);
                    mBitmapStack.Push(mOriginalBitmap);
                    mProcessedBitmap = operations.minFiltering(dialog.MaTrixSize, dialog.EdgeApproach);
                    pbImageViewer.Image = mProcessedBitmap;
                }
            }
        }

        private void menu_maxfilter_Click(object sender, EventArgs e)
        {
            if (pbImageViewer.Image != null)
            {
                FilterSettingDialog dialog = new FilterSettingDialog();
                if (DialogResult.OK == dialog.ShowDialog())
                {
                    mOriginalBitmap = new Bitmap(pbImageViewer.Image);
                    DipOperations operations = new DipOperations(mOriginalBitmap);
                    mBitmapStack.Push(mOriginalBitmap);
                    mProcessedBitmap = operations.maxFiltering(dialog.MaTrixSize, dialog.EdgeApproach);
                    pbImageViewer.Image = mProcessedBitmap;
                }
            }
        }

        private void menu_medianfilter_Click(object sender, EventArgs e)
        {
            if (pbImageViewer.Image != null)
            {
                FilterSettingDialog dialog = new FilterSettingDialog();
                if (DialogResult.OK == dialog.ShowDialog())
                {
                    mOriginalBitmap = new Bitmap(pbImageViewer.Image);
                    DipOperations operations = new DipOperations(mOriginalBitmap);
                    mBitmapStack.Push(mOriginalBitmap);
                    mProcessedBitmap = operations.medianFiltering(dialog.MaTrixSize, dialog.EdgeApproach);
                    pbImageViewer.Image = mProcessedBitmap;
                }
            }
        }

        private void menu_averagefilter_Click(object sender, EventArgs e)
        {

        }

        private void menu_smoothing_Click(object sender, EventArgs e)
        {
            if (pbImageViewer.Image != null)
            {
                FilterSettingDialog dialog = new FilterSettingDialog();
                if (DialogResult.OK == dialog.ShowDialog())
                {
                    mOriginalBitmap = new Bitmap(pbImageViewer.Image);
                    DipOperations operations = new DipOperations(mOriginalBitmap);
                    mBitmapStack.Push(mOriginalBitmap);

                    int size = dialog.MaTrixSize * dialog.MaTrixSize;
                    float[] matrix = new float[size];
                    for (int i = 0; i < size; i++)
                    {
                        matrix[i] = 1f / size;
                    }
                    mProcessedBitmap = operations.smoothingFiltering(matrix, dialog.EdgeApproach);
                    pbImageViewer.Image = mProcessedBitmap;
                }
            }
        }

        private void menu_weighted_Click(object sender, EventArgs e)
        {
            if (pbImageViewer.Image != null)
            {
                mOriginalBitmap = new Bitmap(pbImageViewer.Image);
                DipOperations operations = new DipOperations(mOriginalBitmap);
                mBitmapStack.Push(mOriginalBitmap);

                float[] matrix = new float[9];
                matrix[0] = matrix[2] = matrix[6] = matrix[8] = 1f / 16;
                matrix[1] = matrix[3] = matrix[5] = matrix[7] = 2f / 16;
                matrix[4] = 4f / 16;
                mProcessedBitmap = operations.smoothingFiltering(matrix, FilterUtils.REPLICATE);
                pbImageViewer.Image = mProcessedBitmap;

            }
        }

        private void menu_erosion_Click(object sender, EventArgs e)
        {
            if (pbImageViewer.Image != null)
            {
                mOriginalBitmap = new Bitmap(pbImageViewer.Image);
                DipOperations operations = new DipOperations(mOriginalBitmap);
                mBitmapStack.Push(mOriginalBitmap);
                InputMatrixDialog dialog = new InputMatrixDialog(FilterUtils.BYTE); ;
                if (dialog.ShowDialog() == DialogResult.OK)
                {
                    byte[] matrix = dialog.getDataByte();
                    mProcessedBitmap = operations.erosion(matrix);
                    pbImageViewer.Image = mProcessedBitmap;
                }

            }
        }

        private void menu_dilation_Click(object sender, EventArgs e)
        {
            if (pbImageViewer.Image != null)
            {
                mOriginalBitmap = new Bitmap(pbImageViewer.Image);
                DipOperations operations = new DipOperations(mOriginalBitmap);
                mBitmapStack.Push(mOriginalBitmap);
                InputMatrixDialog dialog = new InputMatrixDialog(FilterUtils.BYTE); ;
                if (dialog.ShowDialog() == DialogResult.OK)
                {
                    byte[] matrix = dialog.getDataByte();
                    mProcessedBitmap = operations.dilation(matrix);
                    pbImageViewer.Image = mProcessedBitmap;
                }
            }
        }

        private void menu_opening_Click(object sender, EventArgs e)
        {
            if (pbImageViewer.Image != null)
            {
                mOriginalBitmap = new Bitmap(pbImageViewer.Image);
                DipOperations operations = new DipOperations(mOriginalBitmap);
                mBitmapStack.Push(mOriginalBitmap);
                InputMatrixDialog dialog = new InputMatrixDialog(FilterUtils.BYTE); ;
                if (dialog.ShowDialog() == DialogResult.OK)
                {
                    byte[] matrix = dialog.getDataByte();
                    mProcessedBitmap = operations.opening(matrix);
                    pbImageViewer.Image = mProcessedBitmap;
                }
            }
        }

        private void menu_closing_Click(object sender, EventArgs e)
        {
            if (pbImageViewer.Image != null)
            {
                mOriginalBitmap = new Bitmap(pbImageViewer.Image);
                DipOperations operations = new DipOperations(mOriginalBitmap);
                mBitmapStack.Push(mOriginalBitmap);
                InputMatrixDialog dialog = new InputMatrixDialog(FilterUtils.BYTE); ;
                if (dialog.ShowDialog() == DialogResult.OK)
                {
                    byte[] matrix = dialog.getDataByte();
                    mProcessedBitmap = operations.closing(matrix);
                    pbImageViewer.Image = mProcessedBitmap;
                }
            }
        }

        private void menu_boundary_Click(object sender, EventArgs e)
        {
            if (pbImageViewer.Image != null)
            {
                mOriginalBitmap = new Bitmap(pbImageViewer.Image);
                DipOperations operations = new DipOperations(mOriginalBitmap);
                mBitmapStack.Push(mOriginalBitmap);
                mProcessedBitmap = operations.boundaryExtraction();
                pbImageViewer.Image = mProcessedBitmap;
            }
        }

        private void menu_laplacian_Click(object sender, EventArgs e)
        {
            if (pbImageViewer.Image != null)
            {
                mOriginalBitmap = new Bitmap(pbImageViewer.Image);
                mBitmapStack.Push(mOriginalBitmap);
                DipOperations operations = new DipOperations(mOriginalBitmap);

                int[] magMatrix = new int[9];
                magMatrix[1] = magMatrix[3] = magMatrix[5] = magMatrix[7] = 1;
                magMatrix[4] = -4;

                mProcessedBitmap = operations.laplacian(magMatrix);
                pbImageViewer.Image = mProcessedBitmap;
            }
        }

        private void menu_sobel_Click(object sender, EventArgs e)
        {
            if (pbImageViewer.Image != null)
            {
                mOriginalBitmap = new Bitmap(pbImageViewer.Image);
                mBitmapStack.Push(mOriginalBitmap);
                DipOperations operations = new DipOperations(mOriginalBitmap);
                mProcessedBitmap = operations.sobel();
                pbImageViewer.Image = mProcessedBitmap;
            }
        }

        private void menu_about_Click(object sender, EventArgs e)
        {
            AboutForm dialog = new AboutForm();
            dialog.ShowDialog();
        }

        private void menu_convert_Click(object sender, EventArgs e)
        {
            if (pbImageViewer.Image != null)
            {
                mOriginalBitmap = new Bitmap(pbImageViewer.Image);
                mBitmapStack.Push(mOriginalBitmap);
                mProcessedBitmap = DipOperations.ConvertToGrayImage(mOriginalBitmap);
                pbImageViewer.Image = mProcessedBitmap;
            }
        }

        #endregion

        private void menu_2xZoom_Click(object sender, EventArgs e)
        {
            if (pbImageViewer.Image != null)
            {
                mOriginalBitmap = new Bitmap(pbImageViewer.Image);
                DipOperations operations = new DipOperations(mOriginalBitmap);
                mBitmapStack.Push(mOriginalBitmap);

                mProcessedBitmap = operations.zoomInZeroOrder(2);
                pbImageViewer.Image = mProcessedBitmap;
            }
        }
    }
}
